package com.zzy.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.zzy.common.core.redis.RedisCache;
import com.zzy.common.utils.EmailUtil;
import com.zzy.common.utils.StringUtils;
import com.zzy.common.utils.guanmai.GuanmaiCommon;
import com.zzy.system.domain.*;
import com.zzy.system.domain.vo.*;
import com.zzy.system.mapper.*;
import com.zzy.system.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class SaleOrderServiceImpl extends ServiceImpl<SaleOrderMapper, SaleOrder> implements ISaleOrderService {
    private static final Logger log = LoggerFactory.getLogger(SaleOrderServiceImpl.class);

    // 注入 RedisCache 对象
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISaleOrderCustomerService iSaleOrderCustomerService;
    @Autowired
    private ISaleOrderDetailService iSaleOrderDetailService;
    @Autowired
    private ISaleOrderDriverService iSaleOrderDriverService;

    @Autowired
    private SaleOrderSupplierMapper saleOrderSupplierMapper;

    @Autowired
    private SaleOrderTraceMapper saleOrderTraceMapper;

    // 定义日期时间格式，与要转换的字符串格式相匹配
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    // 注入配置文件中的观麦令牌在 Redis 中的键名
    @Value("${api.guanmaiTokenKey}")
    private String guanmaiTokenKey;
    // 注入配置文件中的观麦接口 URL
    @Autowired
    private GuanmaiDriverMapper guanmaiDriverMapper;


    //请求观麦 获取订单集合
    @Override
    @Transactional
    public String getGuanmaiSaleOrderList(Integer status, String startDate, String endDate, Integer offset, Integer limit, Integer queryType) throws Exception {
        QueryWrapper<GuanmaiDriver> guanmaiDriverQueryWrapper = new QueryWrapper<>();
        List<GuanmaiDriver> guanmaiDriverList = guanmaiDriverMapper.selectList(guanmaiDriverQueryWrapper);
        List<SaleOrder> allSaleOrderList = new ArrayList<>();

        while (true) {
            Map<String, Object> paramMap = new HashMap<>();
            // 获取今天的日期
            LocalDate today = LocalDate.now();
            // 获取7天前的日期
            LocalDate sevenDaysAgo = today.minusDays(14);

            // 将日期格式化为yyyy-MM-dd格式的字符串
            String startDateStr = sevenDaysAgo.toString();
            String endDateStr = today.toString();

            // 设置开始日期参数
            paramMap.put("start_date", startDateStr);
            // 设置截止日期参数
            paramMap.put("end_date", endDateStr);
            // 订单状态 1:等待分拣 5:分拣中 10:配送中 15: 已签收
            paramMap.put("status", status);
            // 设置分页offset参数（默认值为0，可按需不传该参数或者修改值）
            paramMap.put("offset", offset);
            // 设置分页limit参数（默认值为100，取值范围<=100，可按需不传该参数或者修改值）
            paramMap.put("limit", 100);
            //搜索类型，1: 按照下单时间搜索 2: 按照收货日期搜索
            paramMap.put("query_type", queryType);

            //请求观麦 获取订单列表
            String reponse = GuanmaiCommon.sendRequestGet(paramMap, "/v1/api/order/list/1.1");
            JSONObject reponseJson = JSONObject.parseObject(reponse);
            if (reponseJson.getInteger("code") == 1002) {
                redisCache.deleteObject(guanmaiTokenKey);
                GuanmaiCommon.getGuanmaiToken();
                continue;
            }
            if (reponseJson.get("code").toString().equals("0")) {
                JSONArray jsonArray = reponseJson.getJSONArray("data");
                if (jsonArray != null) {
                    // 将当前页的数据解析并添加到总的结果列表中
                    List<SaleOrder> saleOrderList = jsonArray.toJavaList(SaleOrder.class);
                    allSaleOrderList.addAll(saleOrderList);
                    // 如果返回的数据条数等于每页显示的数量，说明可能还有更多数据，继续查询下一页
                    if (jsonArray.size() == limit) {
                        offset += limit; // 页码增加，指向下一页
                        continue;
                    } else {
                        // 如果返回的数据条数小于每页显示的数量，说明已经查询完所有数据，结束循环
                        break;
                    }
                }
            } else {
                // 如果接口返回的code不是0，表示请求出现问题，这里可以根据实际情况进行错误处理
                System.out.println("请求出现问题，错误信息：" + reponseJson.get("msg"));
                break;
            }

        }

    int batchSize = 100;
        for(
    int i = 0; i<allSaleOrderList.size();i +=batchSize)

    {
        int endIndex = Math.min(i + batchSize, allSaleOrderList.size());
        List<SaleOrder> batchList = allSaleOrderList.subList(i, endIndex);
        // 这里可以将batchList用于实际的saveBatch操作或者其他处理
        System.out.println("当前批次数据量: " + batchList.size());
        batchInsert(batchList, batchSize, guanmaiDriverList, true);
    }

        System.out.println(allSaleOrderList);
        return"";
}


@Override
@Transactional
public String getGuammaiSaleOrderDetails() throws Exception {
    QueryWrapper<SaleOrder> queryWrapper = new QueryWrapper<>();

    // 使用notExists方法结合子查询构建条件，获取不在purchase_order_detail表中的purchase_sheet_id集合
    queryWrapper.select("order_id")
            .notExists("SELECT 1 FROM sale_order_detail WHERE sale_order_detail.order_id = sale_order.order_id");

    List<String> purchaseSheetIdList = baseMapper.selectObjs(queryWrapper).stream()
            .map(obj -> (String) obj)
            .collect(Collectors.toList());
    for (String purchaseSheetId : purchaseSheetIdList) {
        senGauanMaiOrderDetail(purchaseSheetId);
    }
    return "";
}
public void senGauanMaiOrderDetail(String orderId) throws Exception {
    Map<String, Object> paramMap = new HashMap<>();
    // 设置查询order_id
    paramMap.put("order_id", orderId);
    //请求观麦 获取订单列表
    String reponse = GuanmaiCommon.sendRequestGet(paramMap, "/v1/api/order/get/1.1");
    JSONObject reponseJson = JSONObject.parseObject(reponse);
    if (reponseJson.getInteger("code") == 1002) {
        redisCache.deleteObject(guanmaiTokenKey);
        GuanmaiCommon.getGuanmaiToken();
    }
    if (reponseJson.get("code").toString().equals("0")) {
        JSONObject jsonObject = reponseJson.getJSONObject("data");
        SaleOrder saleOrder = JSON.parseObject(jsonObject.toString(), SaleOrder.class);
        if (saleOrder != null && saleOrder.getCustomer() != null) {
            saleOrder.getCustomer().setOrderId(orderId);
            iSaleOrderCustomerService.saveOrderCustomer(saleOrder.getCustomer());
        }
        if (saleOrder != null && !saleOrder.getDetails().isEmpty()) {
            // 使用forEach方法遍历Details集合并设置purchaseSheetId属性
            saleOrder.getDetails().forEach(detail -> detail.setOrderId(orderId));

            iSaleOrderDetailService.saveOrderDetails(saleOrder.getDetails());
        }
        for (SaleOrderDetail saleOrderDetail : saleOrder.getDetails()) {
            if (saleOrderDetail.getCategory2Id() != null) {
                //根据详情中的二级分类id 查询供应商id 和资质
                Map<String, Object> supplierParamMap = new HashMap<>();
                // 设置查询order_id
                supplierParamMap.put("category2_id", saleOrderDetail.getCategory2Id());
                //请求观麦 获取订单列表
                String supplierResponse = GuanmaiCommon.sendRequestGet(paramMap, "/v1/api/stock/supplier/list/1.0");
                JSONObject supplierJson = JSONObject.parseObject(supplierResponse);
                if (supplierJson.getInteger("code") == 1002) {
                    redisCache.deleteObject(guanmaiTokenKey);
                    GuanmaiCommon.getGuanmaiToken();
                    continue;
                }
                if (supplierJson.get("code").toString().equals("0")) {
                    JSONArray supplierJsonJSONArray = supplierJson.getJSONArray("data");
                    if (supplierJsonJSONArray != null) {
                        // 获取供应商数据
                        List<SaleOrderSupplier> saleOrderSuppliers = supplierJsonJSONArray.toJavaList(SaleOrderSupplier.class);
                        if (saleOrderSuppliers != null && saleOrderSuppliers.size() > 0) {
                            for (SaleOrderSupplier saleOrderSupplier : saleOrderSuppliers) {
                                if (saleOrderSupplier.getQualificationImages().size() > 0) {
                                    saleOrderSupplier.setOrderId(orderId);
                                    String images = saleOrderSupplier.getQualificationImages().stream()
                                            .collect(Collectors.joining(","));
                                    saleOrderSupplier.setSupplierImages(images);
                                    QueryWrapper<SaleOrderSupplier> saleOrderSupplierMappe = new QueryWrapper<>();
                                    saleOrderSupplierMappe.eq("detail_id", saleOrderDetail.getDetailId());
                                    saleOrderSupplierMappe.eq("order_id", orderId);

                                    saleOrderSupplierMapper.delete(saleOrderSupplierMappe);
                                    saleOrderSupplier.setDetailId(saleOrderDetail.getDetailId());
                                    saleOrderSupplierMapper.insert(saleOrderSupplier);
                                    break;
                                }
                            }

                        }


                    }
                }
            }

        }

        System.out.println(saleOrder);

    }
}

public void batchInsert(List<SaleOrder> saleOrderList, int batchSize, List<GuanmaiDriver> guanmaiDriverList, Boolean flag) throws Exception {
    // 提前查询数据库中已存在的Orderid集合
    List<String> existingSheetIds = getExistingPurchaseOrderSheetIds(saleOrderList, flag);
    // 过滤掉已存在的orderId对应的记录
    List<SaleOrder> filteredList = filterExistingRecords(saleOrderList, existingSheetIds);
    // 按批次插入过滤后的数据
    int driverIndex = 0; // 用于记录当前取司机信息的索引位置
    boolean reverseDirection = false; // 用于标记是否反向取（从头往前取）
    for (int i = 0; i < filteredList.size(); i += batchSize) {
        List<SaleOrderDriver> saleOrderDriverList = new ArrayList<>();
        int endIndex = Math.min(i + batchSize, filteredList.size());
        List<SaleOrder> batchList = filteredList.subList(i, endIndex);
        System.out.println("当前批次数据量: " + batchList.size());

        // 遍历当前批次的 SaleOrder 列表，获取 orderId 并设置司机相关信息到 SaleOrderDriver 对象
        for (SaleOrder saleOrder : batchList) {
            SaleOrderDriver saleOrderDriver = new SaleOrderDriver();
            // 获取订单ID并设置到 SaleOrderDriver 对象
            saleOrderDriver.setOrderId(saleOrder.getOrderId());
            // 根据索引获取司机信息，并根据情况更新索引和取数方向
            GuanmaiDriver randomDriver = getNextDriver(guanmaiDriverList, driverIndex, reverseDirection);
            if (randomDriver != null) {
                // 设置司机相关信息到 SaleOrderDriver 对象
                saleOrderDriver.setDriverId(randomDriver.getDriverId());
                saleOrderDriver.setDriverName(randomDriver.getDriverName());
                saleOrderDriver.setDriverPhone(randomDriver.getDriverPhone());
                saleOrderDriver.setPlateNumber(randomDriver.getPlateNumber());
            }
            saleOrderDriverList.add(saleOrderDriver);
        }


        this.saveOrUpdateBatch(batchList);
        iSaleOrderDriverService.saveOrderDriver(saleOrderDriverList);
        for (SaleOrder saleOrder : batchList) {

            //循环查询采购入库单的详情
            senGauanMaiOrderDetail(saleOrder.getOrderId());
        }
    }
}

private GuanmaiDriver getNextDriver(List<GuanmaiDriver> driverList, int currentIndex, boolean reverseDirection) {
    int size = driverList.size();
    if (size == 0) {
        return null;
    }

    int indexToUse;
    if (reverseDirection) {
        indexToUse = (currentIndex - 1 + size) % size;
        if (indexToUse == size - 1) {
            reverseDirection = false; // 如果取到了第一个（反向的最后一个），则改为正向取
        }
    } else {
        indexToUse = currentIndex % size;
        if (indexToUse == size - 1) {
            reverseDirection = true; // 如果取到了最后一个，则改为反向取
        }
    }

    currentIndex = indexToUse;
    return driverList.get(indexToUse);
}

private List<String> getExistingPurchaseOrderSheetIds(List<SaleOrder> saleOrders, Boolean flag) {
    if (saleOrders == null || saleOrders.isEmpty()) {
        return new ArrayList<>();
    }

    List<String> sheetIdList = new ArrayList<>();
    for (SaleOrder order : saleOrders) {
        sheetIdList.add(order.getOrderId());
    }

    QueryWrapper<SaleOrder> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("order_id").in("order_id", sheetIdList);
    // 获取当前日期
    LocalDate today = LocalDate.now();
    // 获取15天前的日期
    LocalDate eightDaysAgo = today.minusDays(15);

    // 构建8天前的0点时间（LocalDateTime类型）
    LocalDateTime eightDaysAgoZero = LocalDateTime.of(eightDaysAgo, LocalTime.MIDNIGHT);
    //如果不是true 判断订单是否为15天前 如果为false 则查询所有订单数据
    if (flag) {
        // 添加筛选条件，判断date_time大于等于往前推8天的0点的数据
        queryWrapper.ge("date_time", eightDaysAgoZero);
    }


    return this.getBaseMapper().selectObjs(queryWrapper).stream()
            .map(obj -> (String) obj).collect(Collectors.toList());
}

private List<SaleOrder> filterExistingRecords(List<SaleOrder> saleOrders, List<String> existingSheetIds) {
    List<SaleOrder> saleOrderList = new ArrayList<>();
    for (SaleOrder order : saleOrders) {
        if (!existingSheetIds.contains(order.getOrderId())) {
            saleOrderList.add(order);
        }
    }
    return saleOrderList;
}


}